export default function Fireworks(width, height) {
  const self = this;

  // 产生烟花随机数
  const rand = function (rMi, rMa) {
    // 按位取反运算符
    return ~~(Math.random() * (rMa - rMi + 1) + rMi);
  };

  const hitTest = function (x1, y1, w1, h1, x2, y2, w2, h2) {
    return !(x1 + w1 < x2 || x2 + w2 < x1 || y1 + h1 < y2 || y2 + h2 < y1);
  };

  // 请求动画帧
  window.requestAnimFrame = (function () {
    return (
      window.requestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.oRequestAnimationFrame ||
      window.msRequestAnimationFrame ||
      function (callback) {
        window.setTimeout(callback, 1000 / 60);
      }
    );
  })();

  // 烟花初始化函数
  self.init = function () {
    // self.canvas = document.createElement('canvas')
    self.canvas = document.getElementById("canvas");
    // canvas 全屏
    // self.canvas.width = self.cw = window.innerWidth;
    // self.canvas.height = self.ch = document.body.offsetHeight;
    self.canvas.width = self.cw = width;
    self.canvas.height = self.ch = height;
    self.particles = []; // 粒子数组
    self.partCount = 100;
    self.fireworks = []; // 烟花数组
    self.mx = self.cw / 2; // 最大坐标-x
    self.my = self.ch / 2; // 最大坐标-y
    self.currentHue = 10; // hsl颜色
    self.color = 0; // 0 红色 1 金色
    self.partSpeed = 0.1; // 射出速度
    self.partSpeedVariance = 7; // 差异
    self.partWind = 50;
    self.partFriction = 5; // 摩擦力
    self.partGravity = 2; // 重力
    self.hueMin = 0;
    self.hueMax = 360;
    self.fworkSpeed = 4; // 速度
    self.fworkAccel = 1; // 加速度
    self.hueVariance = 30;
    self.flickerDensity = 25; // 密度
    self.showShockwave = true;
    self.showTarget = false;
    self.clearAlpha = 25;
    // document.body.append(self.canvas)
    self.ctx = self.canvas.getContext("2d");
    self.ctx.lineCap = "round";
    self.ctx.lineJoin = "round";
    self.lineWidth = 1;
    self.bindEvents();
    self.canvasLoop();
    self.canvas.onselectstart = function () {
      return false;
    };
  };
  // 创建粒子
  self.createParticles = function (x, y, hue) {
    let countdown = self.partCount;
    while (countdown--) {
      const newParticle = {
        x: x,
        y: y,
        coordLast: [
          {
            x: x,
            y: y,
          },
          {
            x: x,
            y: y,
          },
          {
            x: x,
            y: y,
          },
        ],
        angle: rand(0, 360),
        speed: rand(
          self.partSpeed - self.partSpeedVariance <= 0
            ? 1
            : self.partSpeed - self.partSpeedVariance,
          self.partSpeed + self.partSpeedVariance
        ),
        friction: 1 - self.partFriction / 100,
        gravity: self.partGravity / 2,
        hue: rand(hue - self.hueVariance, hue + self.hueVariance),
        brightness: rand(50, 80),
        alpha: rand(40, 100) / 100,
        decay: rand(10, 50) / 1000,
        wind: (rand(0, self.partWind) - self.partWind / 2) / 25,
        lineWidth: self.lineWidth,
      };
      self.particles.push(newParticle);
    }
  };
  // 更新粒子
  self.updateParticles = function () {
    let i = self.particles.length;
    while (i--) {
      const p = self.particles[i];
      const radians = (p.angle * Math.PI) / 180;
      const vx = Math.cos(radians) * p.speed;
      const vy = Math.sin(radians) * p.speed;
      p.speed *= p.friction;
      p.coordLast[2].x = p.coordLast[1].x;
      p.coordLast[2].y = p.coordLast[1].y;
      p.coordLast[1].x = p.coordLast[0].x;
      p.coordLast[1].y = p.coordLast[0].y;
      p.coordLast[0].x = p.x;
      p.coordLast[0].y = p.y;
      p.x += vx;
      p.y += vy;
      p.y += p.gravity;
      p.angle += p.wind;
      p.alpha -= p.decay;
      if (
        !hitTest(
          0,
          0,
          self.cw,
          self.ch,
          p.x - p.radius,
          p.y - p.radius,
          p.radius * 2,
          p.radius * 2
        ) ||
        p.alpha < 0.05
      ) {
        self.particles.splice(i, 1);
      }
    }
  };
  // 绘制粒子
  self.drawParticles = function () {
    let i = self.particles.length;
    while (i--) {
      const p = self.particles[i];
      const coordRand = rand(1, 3) - 1;
      self.ctx.beginPath();
      self.ctx.moveTo(
        Math.round(p.coordLast[coordRand].x),
        Math.round(p.coordLast[coordRand].y)
      );
      self.ctx.lineTo(Math.round(p.x), Math.round(p.y));
      self.ctx.closePath();

      if (self.color) {
        self.ctx.strokeStyle = "rgba(245,199,119," + p.alpha + ")";
      } else {
        self.ctx.strokeStyle = "rgba(202,37,47," + p.alpha + ")";
      }

      // self.ctx.strokeStyle = 'hsla(' + p.hue + ', 100%, ' + p.brightness + '%, ' + p.alpha + ')'
      self.ctx.stroke();
      if (self.flickerDensity > 0) {
        const inverseDensity = 50 - self.flickerDensity;
        if (rand(0, inverseDensity) === inverseDensity) {
          self.ctx.beginPath();
          self.ctx.arc(
            Math.round(p.x),
            Math.round(p.y),
            rand(p.lineWidth, p.lineWidth + 3) / 2,
            0,
            Math.PI * 2,
            false
          );
          self.ctx.closePath();
          const randAlpha = rand(50, 100) / 100;

          if (self.color) {
            self.ctx.fillStyle = "rgba(245,199,119," + randAlpha + ")";
          } else {
            self.ctx.fillStyle = "rgba(202,37,47," + randAlpha + ")";
          }

          // self.ctx.fillStyle = 'hsla(' + p.hue + ', 100%, ' + p.brightness + '%, ' + randAlpha + ')'
          self.ctx.fill();
        }
      }
    }
  };
  // 创建烟花
  self.createFireworks = function (startX, startY, targetX, targetY) {
    const newFirework = {
      x: startX,
      y: startY,
      startX: startX,
      startY: startY,
      hitX: false,
      hitY: false,
      coordLast: [
        {
          x: startX,
          y: startY,
        },
        {
          x: startX,
          y: startY,
        },
        {
          x: startX,
          y: startY,
        },
      ],
      targetX: targetX,
      targetY: targetY,
      speed: self.fworkSpeed,
      angle: Math.atan2(targetY - startY, targetX - startX),
      shockwaveAngle:
        Math.atan2(targetY - startY, targetX - startX) + 90 * (Math.PI / 180),
      acceleration: self.fworkAccel / 100,
      hue: self.currentHue,
      brightness: rand(50, 80),
      alpha: rand(50, 100) / 100,
      lineWidth: self.lineWidth,
    };
    self.fireworks.push(newFirework);
  };
  // 更新烟花
  self.updateFireworks = function () {
    let i = self.fireworks.length;
    while (i--) {
      const f = self.fireworks[i];
      self.ctx.lineWidth = f.lineWidth;
      const vx = Math.cos(f.angle) * f.speed;
      const vy = Math.sin(f.angle) * f.speed;
      f.speed *= 1 + f.acceleration;
      f.coordLast[2].x = f.coordLast[1].x;
      f.coordLast[2].y = f.coordLast[1].y;
      f.coordLast[1].x = f.coordLast[0].x;
      f.coordLast[1].y = f.coordLast[0].y;
      f.coordLast[0].x = f.x;
      f.coordLast[0].y = f.y;
      if (f.startX >= f.targetX) {
        if (f.x + vx <= f.targetX) {
          f.x = f.targetX;
          f.hitX = true;
        } else {
          f.x += vx;
        }
      } else {
        if (f.x + vx >= f.targetX) {
          f.x = f.targetX;
          f.hitX = true;
        } else {
          f.x += vx;
        }
      }
      if (f.startY >= f.targetY) {
        if (f.y + vy <= f.targetY) {
          f.y = f.targetY;
          f.hitY = true;
        } else {
          f.y += vy;
        }
      } else {
        if (f.y + vy >= f.targetY) {
          f.y = f.targetY;
          f.hitY = true;
        } else {
          f.y += vy;
        }
      }
      if (f.hitX && f.hitY) {
        self.createParticles(f.targetX, f.targetY, f.hue);
        self.fireworks.splice(i, 1);
      }
    }
  };
  // 绘制烟花
  self.drawFireworks = function () {
    let i = self.fireworks.length;
    self.ctx.globalCompositeOperation = "lighter";
    while (i--) {
      const f = self.fireworks[i];
      self.ctx.lineWidth = f.lineWidth;
      const coordRand = rand(1, 3) - 1;
      self.ctx.beginPath();
      self.ctx.moveTo(
        Math.round(f.coordLast[coordRand].x),
        Math.round(f.coordLast[coordRand].y)
      );
      self.ctx.lineTo(Math.round(f.x), Math.round(f.y));
      self.ctx.closePath();

      if (self.color) {
        self.ctx.strokeStyle = "rgba(245,199,119," + f.alpha + ")";
      } else {
        self.ctx.strokeStyle = "rgba(202,37,47," + f.alpha + ")";
      }

      // self.ctx.strokeStyle = 'hsla(' + f.hue + ', 100%, ' + f.brightness + '%, ' + f.alpha + ')'
      self.ctx.stroke();
      if (self.showTarget) {
        self.ctx.save();
        self.ctx.beginPath();
        self.ctx.arc(
          Math.round(f.targetX),
          Math.round(f.targetY),
          rand(1, 8),
          0,
          Math.PI * 2,
          false
        );
        self.ctx.closePath();
        self.ctx.lineWidth = 1;
        self.ctx.stroke();
        self.ctx.restore();
      }
      if (self.showShockwave) {
        self.ctx.save();
        self.ctx.translate(Math.round(f.x), Math.round(f.y));
        self.ctx.rotate(f.shockwaveAngle);
        self.ctx.beginPath();
        self.ctx.arc(0, 0, 1 * (f.speed / 5), 0, Math.PI, true);

        if (self.color) {
          self.ctx.strokeStyle = "rgba(245,199,119," + rand(25, 60) / 100 + ")";
        } else {
          self.ctx.strokeStyle = "rgba(202,37,47," + rand(25, 60) / 100 + ")";
        }

        // self.ctx.strokeStyle = 'hsla(' + f.hue + ', 100%, ' + f.brightness + '%, ' + rand(25, 60) / 100 +
        //   ')'
        self.ctx.lineWidth = f.lineWidth;
        self.ctx.stroke();
        self.ctx.restore();
      }
    }
  };
  // 绑定事件
  self.bindEvents = function () {
    window.addEventListener("resize", function () {
      clearTimeout(self.timeout);
      self.timeout = setTimeout(function () {
        self.canvas.width = self.cw = window.innerWidth;
        self.canvas.height = self.ch = document.body.offsetHeight;
        self.ctx.lineCap = "round";
        self.ctx.lineJoin = "round";
      }, 100);
    });
    // $(self.canvas).on('mousedown', function (e) {
    //   self.mx = e.pageX - self.canvas.offsetLeft;
    //   self.my = e.pageY - self.canvas.offsetTop;
    //   self.currentHue = rand(self.hueMin, self.hueMax);
    //   self.createFireworks(self.cw / 2, self.ch, self.mx, self.my)
    //   $(self.canvas).on('mousemove.fireworks', function (e) {
    //     self.mx = e.pageX - self.canvas.offsetLeft
    //     self.my = e.pageY - self.canvas.offsetTop
    //     self.currentHue = rand(self.hueMin, self.hueMax)
    //     self.createFireworks(self.cw / 2, self.ch, self.mx, self.my);
    //   })
    // })
    // $(self.canvas).on('mouseup', function (e) {
    //   $(self.canvas).off('mousemove.fireworks')
    // })
  };
  self.clear = function () {
    self.particles = []; // 粒子
    self.fireworks = [];
    self.ctx.clearRect(0, 0, self.cw, self.ch);
  };
  self.canvasLoop = function () {
    requestAnimFrame(self.canvasLoop, self.canvas);
    self.ctx.globalCompositeOperation = "destination-out";
    self.ctx.fillStyle = "rgba(0,0,0," + self.clearAlpha / 100 + ")";
    self.ctx.fillRect(0, 0, self.cw, self.ch);
    self.updateFireworks();
    self.updateParticles();
    self.drawFireworks();
    self.drawParticles();
  };
  self.init();
}
